#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <tolua++.h>
#include <lua.hpp>
#include <lualib.h>
#include <lauxlib.h>

#include "STGObjectManager.h"
#include "Weapon.h"
#include "Player.h"
#include "Creature.h"
#include "Skill.h"

template<> 
CSTGObjectManager* Ogre::Singleton<CSTGObjectManager>::ms_Singleton = 0;

namespace fs = boost::filesystem;
GameObject* CSTGObjectManager::createGameObject(const std::string &type, 
                                               const std::string &name0) 
{
    std::string name(name0);
    boost::to_lower(name);
    if (boost::iequals(type, "weapon")) {
        if (mWeapons.find(name) == mWeapons.end()) {
            GameObject *pObj = new CWeapon(name);
            mWeapons.insert(ObjectDictionary::value_type(name, pObj));
            return pObj;
        }
        else {
            MessageBox(NULL, (name0 + "already exists\n").c_str(), "Caution", MB_OK);
            return NULL;
        }
    }
    if (boost::iequals(type, "skill")) {
        if (mSkills.find(name) == mSkills.end()) {
            GameObject *pObj = new CSkill(name);
            mSkills.insert(ObjectDictionary::value_type(name, pObj));
            return pObj;
        }
        else {
            MessageBox(NULL, (name0 + "already exists\n").c_str(), "Caution", MB_OK);
            return NULL;
        }
    }
    if (boost::iequals(type, "npc")) {
        if (mNPCs.find(name) == mNPCs.end()) {
            GameObject *pObj = new CNPC(name);
            mNPCs.insert(ObjectDictionary::value_type(name, pObj));
            return pObj;
        }
        else {
            MessageBox(NULL, (name0 + "already exists\n").c_str(), "Caution", MB_OK);
            return NULL;
        }
    }
    if (boost::iequals(type, "player")) {
        if (mPlayers.find(name) == mPlayers.end()) {
            GameObject *pObj = new CPlayer(name);
            mPlayers.insert(ObjectDictionary::value_type(name, pObj));
            return pObj;
        }
        else {
            MessageBox(NULL, (name0 + "already exists\n").c_str(), "Caution", MB_OK);
            return NULL;
        }
    }
    return NULL;
}

GameInst* CSTGObjectManager::createWeaponInst( const std::string &weaponType, const std::string &name /*= ""*/ )
{
    ObjectDictionary::iterator iter;

    if ((iter = mWeapons.find(weaponType)) != mWeapons.end()) {
        return dynamic_cast<CWeapon*>(iter->second)->createInstance(name);
    }
    else {
        CWeapon *pWeapon = NULL;
        pWeapon = dynamic_cast<CWeapon*>(createGameObject("weapon", weaponType));
        assert(pWeapon);
        if (pWeapon != NULL) {
            pWeapon->setConfigScript("resource/weapon/" + weaponType + ".lua");
            fs::path old = fs::current_path();
            fs::current_path(static_cast<CSTGEngine*>(CSTGEngine::getSingletonPtr())->folder());
            pWeapon->loadConfigScript();
            fs::current_path(old);
            return pWeapon->createInstance(name);
        }
        else {
            GAME_LOG("weapon: "+ weaponType + " not found\n");
            return NULL;
        }
    }
}

void CSTGObjectManager::destoryGameObject( const std::string &type, const std::string &name )
{
    ObjectDictionary::iterator iter;
    for (iter = mPlayers.begin(); iter != mPlayers.end(); ++iter) {
        delete iter->second;
    }
    for (iter = mNPCs.begin(); iter != mNPCs.end(); ++iter) {
        delete iter->second;
    }
    for (iter = mWeapons.begin(); iter != mWeapons.end(); ++iter) {
        delete iter->second;
    }
    for (iter = mSkills.begin(); iter != mSkills.end(); ++iter) {
        delete iter->second;
    }
    //return NULL;
}

void CSTGObjectManager::loadAll()
{
    //for ()
    static lua_State *L = static_cast<CSTGEngine*>(CSTGEngine::getSingletonPtr())->lua();
    fs::path root(static_cast<CSTGEngine*>(CSTGEngine::getSingletonPtr())->folder());
    // load all clips
    fs::path folder = root/"resource/clip";
    if (fs::exists(folder)) {
        fs::directory_iterator end;
        for (fs::directory_iterator iter(folder); iter != end; ++iter) {
            if (fs::is_regular_file(*iter)) {
                std::string name = iter->filename();
                if (boost::find_first(name, "barrage_")) {
                    if (luaL_dofile(L, iter->string().c_str())) 
                        LUA_ERROR(L);
                }
                else if (boost::find_first(name, "bullet_")) {
                    if (luaL_dofile(L, iter->string().c_str())) 
                        LUA_ERROR(L);
                }
            }
        }
    }
    else {
        GAME_LOG("resource/clip does not exists");
    }
    // load all w
    folder = root/"resource/weapon";
    if (fs::exists(folder)) {
        fs::directory_iterator end;
        for (fs::directory_iterator iter(folder); iter != end; ++iter) {
            if (fs::is_regular_file(*iter)) {
                CWeapon *pWeapon = dynamic_cast<CWeapon*>(createGameObject("weapon", fs::basename(*iter))) ;
                pWeapon->setConfigScript(iter->string());
                pWeapon->loadConfigScript();
            }
        }
    }
}












